package com.mobilesalon.report.engine;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import android.database.Cursor;
import android.os.Environment;
import android.provider.BaseColumns;
import android.util.Log;

import com.mobilesalon.tools.StringUtils;

public class ReportExporter {

	private static final String TAG = ReportExporter.class.getName();

	private static final String REPORT_EXPORT_PATH = Environment.getExternalStorageDirectory()
			+ "/MobileSalon/";

	private boolean externalStorageAvailable;
	private boolean externalStorageWriteable;

	public ReportExporter() {

	}

	public File generate(String[] headers, Cursor cursor, String[] footers) throws ReportException {

		//
		// Setup file storage
		//
		this.refreshStorageAvailability();
		if (!externalStorageAvailable) {
			throw new ReportException(false, false);
		}
		if (!externalStorageWriteable) {
			throw new ReportException(true, false);
		}

		File outputReportDirectory = new File(REPORT_EXPORT_PATH);
		if (!outputReportDirectory.isDirectory()) {
			outputReportDirectory.delete();
			outputReportDirectory.mkdir();
		}

		//
		// Generate report
		//
		
		//header
		StringBuilder headerString = StringUtils.splitWithPreserveTokens(headers, ";");
		
		//footer
		StringBuilder footerString = StringUtils.splitWithPreserveTokens(footers, ";");

		//body
		StringBuilder bodyString = new StringBuilder();

		String[] columns = cursor.getColumnNames();
		int columnCount = columns.length;

		if (cursor.moveToFirst() == true) {
			do {
				List<String> bodyLine = new ArrayList<String>();
				for (int i = 0; i < columnCount; i++) {
					if (!BaseColumns._ID.equals(columns[i])) { // skip "_id" column
						String cellContent = cursor.getString(cursor.getColumnIndex(columns[i]));
						bodyLine.add(cellContent);
					}
				}

				bodyString.append(
						StringUtils.splitWithPreserveTokens(bodyLine.toArray(new String[0]), ";"))
						.append("\n");

			} while (cursor.moveToNext());
		}

		//
		// write the file
		//

		String reportFileName = "Report_" + Calendar.getInstance().getTimeInMillis() + ".csv";
		File file = new File(REPORT_EXPORT_PATH, reportFileName);

		Log.i(TAG, "Try to export the report+" + file);

		try {
			OutputStream bout = new BufferedOutputStream(new FileOutputStream(file)); // buffer
			OutputStreamWriter out = new OutputStreamWriter(bout, "8859_1"); // Conversion
																				// for
																				// windows
																				// reading
			PrintWriter writer = new PrintWriter(out); // convenient writing
														// methods
			writer.println(headerString.toString());
			writer.println(bodyString.toString());
			writer.println(footerString.toString());
			writer.flush();
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			throw new ReportException(externalStorageAvailable, externalStorageWriteable);
		}

		return file;

	}

	private void refreshStorageAvailability() {
		externalStorageAvailable = false;
		externalStorageWriteable = false;
		String state = Environment.getExternalStorageState();

		if (Environment.MEDIA_MOUNTED.equals(state)) {
			// We can read and write the media
			externalStorageAvailable = externalStorageWriteable = true;
		} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
			// We can only read the media
			externalStorageAvailable = true;
			externalStorageWriteable = false;
		} else {
			// Something else is wrong. It may be one of many other states, but
			// all we need
			// to know is we can neither read nor write
			externalStorageAvailable = externalStorageWriteable = false;
		}
	}

}
